package ru.passivemoney.indicator.ac.optimization;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.passivemoney.common.Credentials;
import ru.passivemoney.common.Utils;
import ru.passivemoney.indicator.AIndicator;
import ru.passivemoney.indicator.CommonParameters;
import ru.passivemoney.indicator.ac.ACSpecParams;
import ru.passivemoney.indicator.ac.iAC;
import ru.passivemoney.strategy.IndicatorStrategy;

import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.system.ITesterClient;
import com.dukascopy.api.system.TesterFactory;
import com.rits.cloning.Cloner;

public class ACOptimization {
	private static final Logger logger = LoggerFactory.getLogger(ACOptimization.class);

	private static final List<ITesterClient> clients = new ArrayList<ITesterClient>();

	private static void initClients() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InterruptedException, ExecutionException, ParseException {
		final ITesterClient client = TesterFactory.getDefaultInstance();
		Cloner cloner = new Cloner();

		for (Credentials credentials : Credentials.CLIENT_CREDENTIALS) {
			clients.add(initClient(cloner.deepClone(client), credentials));
		}
	}

	private static ITesterClient initClient(ITesterClient cl, Credentials credentials) throws InterruptedException, ExecutionException, ParseException {
		cl.setSystemListener(new ACOptimizationListener(cl, credentials));
		Utils.connectClientInfinity(cl, credentials);
		cl.setInitialDeposit(Instrument.EURUSD.getSecondaryCurrency(), 1000);
		
		Set<Instrument> instruments = new HashSet<Instrument>();
		instruments.add(Instrument.EURUSD);
//		for(Instrument instrument : Instrument.values()){
//			instruments.add(instrument);
//		}
		cl.setSubscribedInstruments(instruments);
		
		cl.setDataInterval(ITesterClient.DataLoadingMethod.DIFFERENT_PRICE_TICKS, Utils.SDF.parse("2013-10-03 00:00:00").getTime(), Utils.SDF.parse("2013-10-04 23:59:59").getTime());
		File cacheDir = new File("c:\\WORK\\JForex\\cache\\");
		//cl.setCacheDirectory(cacheDir);
		Future<?> future = cl.downloadData(null);
		while(!future.isDone()){
			Thread.sleep(1000);
		}
		return cl;
	}

	public static ITesterClient getClientFromPool() {
		while (true) {
			synchronized (clients) {
				if (clients.size() > 0) {
					ITesterClient c = clients.iterator().next();
					clients.remove(c);
					return c;
				}
			}
			try {
				Thread.sleep(10000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public synchronized void releaseClient(ITesterClient c) {
		clients.add(c);
	}

	public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InterruptedException, ExecutionException, ParseException {
		// 1. Инициируем клиентов
		initClients();
		
		// 2. Формируем список инструментов
		Set<Instrument> instruments = new HashSet<Instrument>();
		instruments.add(Instrument.EURUSD);

		// 3. Формируем массив разных настроек для тестирования
		Period[] periods = new Period[] { 
				Period.ONE_MIN, 
				Period.FIVE_MINS,
				Period.FIFTEEN_MINS, 
				Period.THIRTY_MINS, 
				Period.ONE_HOUR,
				Period.FOUR_HOURS, 
				Period.DAILY, 
				Period.WEEKLY };
		
		OfferSide[] offerSides = new OfferSide[] { OfferSide.ASK, OfferSide.BID };
		
		AppliedPrice[] appliedPrices = new AppliedPrice[] { 
				AppliedPrice.OPEN,
				AppliedPrice.CLOSE,
				AppliedPrice.LOW,
				AppliedPrice.HIGH,
				AppliedPrice.MEDIAN_PRICE,
				AppliedPrice.TIMESTAMP,
				AppliedPrice.TYPICAL_PRICE,
				AppliedPrice.VOLUME,
				AppliedPrice.WEIGHTED_CLOSE};
		
		int[] shifts = new int[] { 1, 2, 3, 4, 5 };

		int[] fastPeriods = new int[] { 4, 5, 6, 7, 8, 9, 10 };
		int[] slowPeriods = new int[] { 11, 12, 13, 14, 15, 16, 17 };

//		Work[] works = new Work[periods.length * offerSides.length * appliedPrices.length * shifts.length * fastPeriods.length * slowPeriods.length];
//		int counter = 0;
//
//		for (Instrument instrument : instruments) {
//			for (Period p : periods) {
//				for (OfferSide os : offerSides) {
//					for (AppliedPrice ap : appliedPrices) {
//						for (int shift : shifts) {
//							CommonParameters commonParameters = new CommonParameters();
//							commonParameters.setAppliedPrice(ap);
//							commonParameters.setOfferSide(os);
//							commonParameters.setPeriod(p);
//							commonParameters.setShift(shift);
//							for (int fastPeriod : fastPeriods) {
//								for (int slowPeriod : slowPeriods) {
//									Set<AIndicator> indicators = new HashSet<AIndicator>();
//									indicators.add(new iAC(commonParameters, new ACSpecParams(fastPeriod, slowPeriod)));
//	
//									IndicatorStrategy indicatorStrategy = new IndicatorStrategy();
//									indicatorStrategy.setIndicators(indicators);
//	
//									works[counter++] = new Work(instrument, indicatorStrategy);
//								}
//							}
//						}
//					}
//				}
//			}
//		}
//
//		// 3. Запускаем тесты
//		works[0].setClient(getClientFromPool());
//		works[0].run();
		
		// 4. Анализируем отчёты
	}
}
